package com.working.libcommon.bus

import androidx.annotation.MainThread
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.Type
import kotlin.collections.set

/**
 *
 * 注册事件 :通过with方法获得一个[MutableLiveData]实例 然后在[androidx.activity.ComponentActivity] 或者[androidx.fragment.app.Fragment]中订阅即可
 * 发送事件 :通过with方法获得一个[MutableLiveData]实例 然后[MutableLiveData.postValue]即可
 *
 * 例
 * ActivityA:Activity{
 *      override fun onCreate(savedInstanceState: Bundle?) {
 *          LiveDataBus.with<Long>("Event1", this) {  //订阅事件name为"Event1" eventData类型为Long的事件
 *              Timber.tag("AAA").e("LiveDataBus${System.currentTimeMillis() - it}")
 *          }
 *          或者
 *          LiveDataBus.with<Long>(this) {  //订阅所有eventData类型为Long的事件
 *              Timber.tag("AAA").e("LiveDataBus${System.currentTimeMillis() - it}")
 *          }
 *      }
 * }
 *
 * ActivityB:Activity{
 *      override fun onCreate(savedInstanceState: Bundle?) {
 *          LiveDataBus.with<Long>("Event1").postValue(System.currentTimeMillis())
 *          或者
 *          LiveDataBus.with<Long>().postValue(System.currentTimeMillis())
 *      }
 * }
 *
 */
@Suppress("UNCHECKED_CAST")
object LiveDataBus {
    private val bus: MutableMap<String, BusMutableLiveData<*>> = hashMapOf()

    fun <T> with(key: String): MutableLiveData<T> {
        if (key !in bus) {
            bus[key] = BusMutableLiveData<T>()
        }
        return bus[key] as MutableLiveData<T>
    }

    inline fun <reified T> send(value: T) {
        with<T>().postValue(value)
    }

    @MainThread
    inline fun <reified T> with(): MutableLiveData<T> {
        return with(T::class.java.name)
    }

    @MainThread
    inline fun <reified T> with(owner: LifecycleOwner, crossinline observer: (T) -> Unit) {
        with<T>().observe(owner, Observer { observer.invoke(it) })
    }

    fun <T> with(key: String, owner: LifecycleOwner, observer: (T) -> Unit) {
        with<T>(key).observe(owner, Observer { observer.invoke(it) })
    }

    private class Wrapper<T>(val observer: Observer<T>) : Observer<T> {
        override fun onChanged(t: T?) {
            if (isCallOnObserve) {
                return
            }
            observer.onChanged(t)
        }

        private val isCallOnObserve: Boolean
            get() {
                val stackTrace = Thread.currentThread().stackTrace
                if (stackTrace.isNotEmpty()) {
                    for (element in stackTrace) {
                        if ("android.arch.lifecycle.LiveData" == element?.className && "observeForever" == element.methodName) {
                            return true
                        }
                    }
                }
                return false
            }
    }

    private class BusMutableLiveData<T> : MutableLiveData<T>() {
        private val observerMap: MutableMap<Observer<in T>, Wrapper<in T>> = HashMap()
        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)
            try {
                // 设置observer的version和LiveData一致
                hook(observer)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun observeForever(observer: Observer<in T>) {
            if (observer !in observerMap) {
                observerMap[observer] = Wrapper(observer)
            }
            super.observeForever(observerMap[observer]!!)
        }

        override fun removeObserver(observer: Observer<in T>) {
            val realObserver = if (observer in observerMap) {
                observerMap.remove(observer)!!
            } else {
                observer
            }

            super.removeObserver(realObserver)
        }

        @Throws(Exception::class)
        private fun hook(observer: Observer<*>) {
            // 获取livedata的class对象
            val classLiveData: Class<LiveData<*>> = LiveData::class.java
            // 获取   LiveData类的mObservers对象 （Map对象）的 Field对象
            val fieldObservers: Field = classLiveData.getDeclaredField("mObservers")
            // 将mObservers 的private设置为 public
            fieldObservers.isAccessible = true
            //  获取当前livedata的mObservers对象(map)
            val objectObservers: Any? = fieldObservers.get(this)
            // 拿到mObservers（map）的class对象
            val classObservers: Class<*>? = objectObservers?.javaClass
            // 通过map的class对象拿到get（）的method对象
            val methodGet: Method? = classObservers?.getDeclaredMethod("get", Any::class.java)
            methodGet?.isAccessible = true
            // 通过map 的 get Method对象 拿到值 （Entry）  （arg1：map ，arg2：key ）
            val objectWrapperEntry: Any? = methodGet?.invoke(objectObservers, observer)
            // 拿到wrapper
            var objectWrapper: Any? = null
            if (objectWrapperEntry is MutableMap.MutableEntry<*, *>) {
                objectWrapper =
                    objectWrapperEntry.value
            }
            if (objectWrapper == null) {
                throw NullPointerException("Wrapper can not be null!")
            }
            // 反射wrapper对象
            val classObserverWrapper = objectWrapper.javaClass.superclass
            // 拿到wrapper的version
            val fieldLastVersion: Field? = classObserverWrapper?.getDeclaredField("mLastVersion")
            fieldLastVersion?.isAccessible = true
            //get livedata's version
            val fieldVersion: Field = classLiveData.getDeclaredField("mVersion")
            fieldVersion.isAccessible = true
            val objectVersion = fieldVersion.get(this)
            //set wrapper's version
            fieldLastVersion?.set(objectWrapper, objectVersion)
        }
    }
}